package cn.accjiyun.pki.service.impl;

import cn.accjiyun.pki.common.entity.PageModel;
import cn.accjiyun.pki.common.entity.QueryEntity;
import cn.accjiyun.pki.common.utils.Base64;
import cn.accjiyun.pki.common.utils.BytesHexConverter;
import cn.accjiyun.pki.common.utils.BytesIOConverter;
import cn.accjiyun.pki.dao.PacketsDao;
import cn.accjiyun.pki.entity.CAConfig;
import cn.accjiyun.pki.entity.Packets;
import cn.accjiyun.pki.entity.SystemUser;
import cn.accjiyun.pki.entity.Tax;
import cn.accjiyun.pki.security.AESUtil;
import cn.accjiyun.pki.security.RSAUtils;
import cn.accjiyun.pki.service.PacketsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.List;

/**
 * Created by jiyun on 2017/5/18.
 */
@Service("packetsService")
public class PacketsServiceImpl implements PacketsService {

    @Autowired
    private PacketsDao packetsDao;

    /**
     * 创建数据包
     *
     * @param packets 数据包实体
     * @return 数据包ID
     */
    @Override
    public int createPackets(Packets packets) {
        return packetsDao.createPackets(packets);
    }

    /**
     * 通过数据包ID数组删除数据包
     *
     * @param packetsIds 数据包ID数组
     */
    @Override
    public void deletePackets(int[] packetsIds) {
        packetsDao.deletePackets(packetsIds);
    }

    /**
     * 通过数据包ID查询数据包信息
     *
     * @param packetsId 庭成员ID
     * @return 数据包实体
     */
    @Override
    public Packets queryPacketsById(int packetsId) {
        return packetsDao.queryPacketsById(packetsId);
    }

    /**
     * 分页查询数据包信息
     *
     * @param queryEntity 查询条件实体
     * @param model       分页实体
     * @return 数据包实体列表
     */
    @Override
    public List<Packets> queryPacketsPage(QueryEntity queryEntity, PageModel<Packets> model) {
        return packetsDao.queryPacketsPage(queryEntity, model);
    }

    /**
     * 更新数据包信息
     *
     * @param packets 数据包实体
     */
    @Override
    public void updatePackets(Packets packets) {
        packetsDao.updatePackets(packets);
    }

    /**
     * 获取数据包总数
     *
     * @return 数据包总数
     */
    @Override
    public long queryAllPacketsCount() {
        return packetsDao.queryAllPacketsCount();
    }

    /**
     * 利用hql语句查找数据包信息列表
     *
     * @param hql         查询语句
     * @param queryParams 查询参数
     * @return 数据包实体列表
     */
    @Override
    public List<Packets> createQuery(String hql, Object[] queryParams) {
        return packetsDao.createQuery(hql, queryParams);
    }

    /**
     * 根据数字签名审核验证
     *
     * @param tax
     * @param realAttachUrl
     * @return
     */
    @Override
    public boolean audit(Tax tax, String realAttachUrl) {
        SystemUser systemUser = tax.getSystemUserByUserId();
        Packets packets = packetsDao.queryPacketsById(tax.getId());
        //申报人公钥
        PublicKey publicKey = RSAUtils.readCer(systemUser.getPukUrl());

        //加密文本
        byte[] cipherTextBytes = BytesHexConverter.HexString2Bytes(packets.getEncryptContent());
        //文本签名
        byte[] textSignBytes = BytesHexConverter.HexString2Bytes(packets.getTextSign());
        //文本验证
        boolean isTextValid = RSAUtils.verify(publicKey.getEncoded(), RSAUtils.MdigestSHA(cipherTextBytes), textSignBytes);

        boolean isFileValid = true;
        if (realAttachUrl != null) {
            //加密附件
            byte[] base64FileBytes = BytesIOConverter.fileToBytes(realAttachUrl);
            //附件签名
            byte[] fileSignBytes = BytesHexConverter.HexString2Bytes(packets.getFileSign());
            //附件验证
            isFileValid = RSAUtils.verify(publicKey.getEncoded(), RSAUtils.MdigestSHA(base64FileBytes), fileSignBytes);
        }
        return isTextValid && isFileValid;
    }

    /**
     * 将申报信息加密、生成数字签名打包
     *
     * @param packets       数据包
     * @param content       申报信息
     * @param realAttachUrl 附件路径
     * @param pfxPath       申报人pfx证书路径
     * @param password      申报人pfx证书密码
     * @return 打包后的Packers数据包实例
     */
    @Override
    public Packets packedMessage(Packets packets, String content, String realAttachUrl, String pfxPath, String password) {

        //承办人公钥
//        String pubPath = handlePath(cerPath + "root.cer");
        PublicKey publicKey = RSAUtils.readCer("D:/pki/root.cer");
        //申报人私钥
        CAConfig caConfig = new CAConfig();
        caConfig.setPK_PASSWORD(password);
        PrivateKey privateKey = RSAUtils.readPKCS12(pfxPath, caConfig);
        if (privateKey == null) return null;

        //生成AES密钥
        byte[] AESKeyBytes = AESUtil.initkey();
        //RSA公钥加密AES密钥
        byte[] cipherKeyBytes = RSAUtils.encryptByRSA(publicKey.getEncoded(), AESKeyBytes);

        packets.setCipherAesKey(BytesHexConverter.Bytes2HexString(cipherKeyBytes));

        //加密文本
        byte[] cipherTextBytes = AESUtil.encrypt(content.getBytes(), AESKeyBytes);
        //签名
        byte[] textSignBytes = RSAUtils.sign(privateKey.getEncoded(), RSAUtils.MdigestSHA(cipherTextBytes));

        packets.setEncryptContent(BytesHexConverter.Bytes2HexString(cipherTextBytes));
        packets.setTextSign(BytesHexConverter.Bytes2HexString(textSignBytes));

        if (realAttachUrl != null) {
            // 加密文件
            byte[] fileBytes = BytesIOConverter.fileToBytes(realAttachUrl);
            new File(realAttachUrl).delete();
            byte[] cipherFileBytes = AESUtil.encrypt(fileBytes, AESKeyBytes);
            byte[] base64FileBytes = Base64.encodeToByte(cipherFileBytes);
            BytesIOConverter.BytesToFile(base64FileBytes, realAttachUrl.replaceAll("_plain", ""));
            //签名文件
            byte[] fileSignBytes = RSAUtils.sign(privateKey.getEncoded(), RSAUtils.MdigestSHA(base64FileBytes));

            packets.setFileSign(BytesHexConverter.Bytes2HexString(fileSignBytes));
        }

        return packets;
    }
}
